package com.dotflat.check.service.impl;

import com.dotflat.check.domain.Checker;
import com.dotflat.check.repository.CheckInRulerRepository;
import com.dotflat.check.repository.CheckerRepository;
import com.dotflat.check.service.CCheckerService;
import com.dotflat.util.Base64ToFile;
import com.matt.domain.Children;
import com.matt.domain.ChildrenExtendInfo;
import com.matt.domain.ChildrenNurseryInfoRecord;
import com.matt.domain.record.CheckInRule;
import com.matt.domain.record.CheckRecord;
import com.matt.domain.rel.RelClassesChildren;
import com.matt.foundation.utils.DateUtil;
import com.matt.repository.ChildrenExtendInfoRepository;
import com.matt.repository.ChildrenRepository;
import com.matt.repository.record.CheckRecordRepository;
import com.matt.repository.record.ChildrenNurseryInfoRecordRepository;
import com.matt.repository.rel.RelClassesChildrenRepository;
import com.matt.service.UploadService;
import com.matt.service.remoteCall.SsoCallService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.*;


@Service
public class CCheckerServiceImpl implements CCheckerService {

    @Autowired
    private CheckerRepository checkerRepository;

    @Autowired
    private SsoCallService ssoCallService;

    @Autowired
    private UploadService uploadService;

    @Autowired
    private ChildrenRepository childrenRepository;

    @Autowired
    private ChildrenNurseryInfoRecordRepository childrenNurseryInfoRecordRepository;

    @Autowired
    private ChildrenExtendInfoRepository childrenExtendInfoRepository;

    @Autowired
    private CheckRecordRepository checkRecordRepository;
    @Autowired
    private RelClassesChildrenRepository relClassesChildrenRepository;

    @Autowired
    private CheckInRulerRepository checkInRulerRepository;

    private static final Logger log = LoggerFactory.getLogger(CCheckerServiceImpl.class);

    @Override
//    public CheckRecord checkinChildren(Checker checker, String childrenId, String captureImage, Date checkTime, double personTemperature) {
//        // 1. 定义当天时间范围（0点-23:59:59）
//        Date now = new Date();
//        String currentDay = DateUtil.millisToDateTime(now.getTime(), "yyyy-MM-dd");
//        Map<String, Date> map = DateUtil.getCurrentDayBeginAndEnd(currentDay);
//        Date begin = map.get("beg");
//        Date end = map.get("end");
//
//        // 2. 基础校验：幼儿存在性
//        Children children = childrenRepository.findFirstById(childrenId);
//        if (children == null) {
//            log.warn("幼儿[childrenId:{}]不存在，拒绝打卡", childrenId);
//            return null;
//        }
//
//        // 3. 基础校验：考勤规则存在性（启用状态+对应区域）
//        CheckInRule rule = checkInRulerRepository.findByEnableStatusAndAreaId(1, children.getAreaId());
//        if (rule == null) {
//            log.warn("幼儿[childrenId:{}]所属区域无启用的考勤规则，拒绝打卡", childrenId);
//            return null;
//        }
//
//        // 4. 核心：查询当天唯一记录（一天一条，复用/新建）
//        CheckRecord record = checkRecordRepository.findFirstByCheckInTimeBetweenAndChildrenId(begin, end, childrenId);
//        log.info("幼儿[childrenId:{}]当天记录查询结果：{}",
//                childrenId, record == null ? "无记录，将创建新记录" : "已存在记录，将更新对应字段");
//
//        // 5. 关联班级信息（用于记录班级ID）
//        RelClassesChildren relClassesChildren = relClassesChildrenRepository.findFirstByChildrenId(childrenId);
//        String classesId = relClassesChildren != null ? relClassesChildren.getClassesId() : null;
//
//        // 6. 时间格式转换（LocalDateTime便于时间范围判断）
//        LocalDateTime checkLocalTime = checkTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
//
//        // 7. 校验：当天是否为打卡日（按规则配置的星期几）
//        boolean isCheckDay = false;
//        if (StringUtils.hasText(rule.getCheckDays())) {
//            int currentWeekDay = checkLocalTime.getDayOfWeek().getValue(); // 1=周一，7=周日
//            isCheckDay = Arrays.asList(rule.getCheckDays().split(",")).contains(String.valueOf(currentWeekDay));
//        }
//        if (!isCheckDay) {
//            log.warn("幼儿[childrenId:{}]当天非打卡日（星期{}），拒绝打卡", childrenId, checkLocalTime.getDayOfWeek().getValue());
//            return null;
//        }
//
//        // 8. 图片上传（如有）：入园/出园共用同一张图（或按需区分，此处保持原逻辑）
//        String image = "";
//        if (org.apache.commons.lang3.StringUtils.isNotBlank(captureImage)) {
//            String fileName = "checkin_" + childrenId + "_" + System.currentTimeMillis() + ".jpg"; // 文件名加时间戳，避免重复
//            MultipartFile fileV1 = Base64ToFile.base64ToMultipartFile(captureImage, fileName);
//            image = uploadService.uploadCheckInRecordImg(childrenId, fileV1);
//            log.info("幼儿[childrenId:{}]打卡图片上传完成，路径：{}", childrenId, image);
//        }
//
//        // 9. 初始化记录（无记录则新建，有记录则复用）
//        if (record == null) {
//            record = new CheckRecord();
//            // 基础字段初始化（仅新建时设置，后续更新不覆盖）
//            record.setChildrenId(childrenId);
//            record.setClassesId(classesId);
//            record.setUserType(1); // 固定为“幼儿”类型
//            record.setCheckerId(checker.getId());
//            record.setCheckerAddress(checker.getAddress());
//            record.setGroupFlag(currentDay); // 日期分组标识（便于后续查询）
//            // 状态字段默认值（数据库已设default 0，代码显式设置更安全）
//            record.setStatus(0); // 入园状态默认“缺席”
//            record.setLeaveStatus(0); // 离园状态默认“未离园”
//        }
//        // 每次打卡都更新最新温度（无论入园/出园）
//        record.setTemperature(String.valueOf(personTemperature));
//
//        CheckRecord resultRecord = null;
//
//        // 10. 处理考勤机方向：3=自动判断入园/出园（核心场景）
//        if (checker.getDirection() == 3) {
//            // 10.1 自动判断：入园操作（满足2个条件：未记录入园状态 + 在入园时间范围内）
//            if (record.getStatus() == 0 && isInCheckInTimeRange(checkLocalTime, rule)) {
//                // 计算入园状态（正常1 / 迟到5）
//                LocalDateTime ruleCheckInTime = rule.getCheckInTime();
//                LocalDateTime shouldCheckInTime = LocalDateTime.of(
//                        checkLocalTime.getYear(), checkLocalTime.getMonth(), checkLocalTime.getDayOfMonth(),
//                        ruleCheckInTime.getHour(), ruleCheckInTime.getMinute(), 0
//                );
//                // 迟到阈值：规则有值则用规则，无则默认10分钟（过滤负数）
//                int lateThreshold = Optional.ofNullable(rule.getLateAbsentRule())
//                        .filter(threshold -> threshold >= 0)
//                        .orElse(10);
//                long lateMinutes = ChronoUnit.MINUTES.between(shouldCheckInTime, checkLocalTime);
//
//                // 更新入园相关字段（仅更新入园状态，不碰离园字段）
//                record.setStatus(lateMinutes > lateThreshold ? 5 : 1); // 迟到→5，正常→1
//                record.setCheckInTime(checkTime);
//                record.setCheckInMediaUrl(image);
//
//                resultRecord = checkRecordRepository.save(record);
//                log.info("幼儿[childrenId:{}]自动入园成功，状态：{}（1=正常，5=迟到），打卡时间：{}",
//                        childrenId, record.getStatus(), checkTime);
//
//                // 10.2 自动判断：出园操作（满足2个条件：已记录入园状态 + 在出园时间范围内）
//            } else if (record.getStatus() != 0 && isInCheckOutTimeRange(checkLocalTime, rule)) {
//                // 计算离园状态（正常2 / 早退6）
//                LocalDateTime ruleCheckOutTime = rule.getCheckOutTime();
//                LocalDateTime shouldCheckOutTime = LocalDateTime.of(
//                        checkLocalTime.getYear(), checkLocalTime.getMonth(), checkLocalTime.getDayOfMonth(),
//                        ruleCheckOutTime.getHour(), ruleCheckOutTime.getMinute(), 0
//                );
//                // 早退阈值：规则有值则用规则，无则默认30分钟（过滤负数）
//                int earlyThreshold = Optional.ofNullable(rule.getEarlyAbsentRule())
//                        .filter(threshold -> threshold >= 0)
//                        .orElse(30);
//                long earlyMinutes = ChronoUnit.MINUTES.between(checkLocalTime, shouldCheckOutTime);
//
//                // 更新离园相关字段（仅更新离园状态，不碰入园字段）
//                record.setLeaveStatus(earlyMinutes > earlyThreshold ? 6 : 2); // 早退→6，正常→2
//                record.setCheckOutTime(checkTime);
//                record.setCheckOutMediaUrl(image);
//
//                resultRecord = checkRecordRepository.save(record);
//                log.info("幼儿[childrenId:{}]自动出园成功，状态：{}（2=正常，6=早退），打卡时间：{}",
//                        childrenId, record.getLeaveStatus(), checkTime);
//            } else {
//                log.warn("幼儿[childrenId:{}]自动打卡条件不满足：当前入园状态={}，是否在入园范围={}，是否在出园范围={}",
//                        childrenId, record.getStatus(),
//                        isInCheckInTimeRange(checkLocalTime, rule),
//                        isInCheckOutTimeRange(checkLocalTime, rule));
//            }
//
//            // 11. 处理考勤机方向：1=仅入园（强制入园，不判断自动逻辑）
//        } else if (checker.getDirection() == 1) {
//            // 仅当入园状态为默认0（未入园）时才更新
//            if (record.getStatus() == 0) {
//                record.setStatus(1); // 强制“正常入园”（按需求可调整为自动判断迟到）
//                record.setCheckInTime(checkTime);
//                record.setCheckInMediaUrl(image);
//
//                resultRecord = checkRecordRepository.save(record);
//                log.info("幼儿[childrenId:{}]强制入园成功，状态：1（正常），打卡时间：{}",
//                        childrenId, checkTime);
//            } else {
//                resultRecord = record;
//                log.info("幼儿[childrenId:{}]已存在入园记录（状态：{}），无需重复入园",
//                        childrenId, record.getStatus());
//            }
//
//            // 12. 处理考勤机方向：2=仅出园（强制出园，不判断自动逻辑）
//        } else if (checker.getDirection() == 2) {
//            // 必须有入园记录（status≠0）才允许出园
//            if (record.getStatus() != 0) {
//                // 仅当离园状态为默认0（未离园）时才更新
//                if (record.getLeaveStatus() == 0) {
//                    record.setLeaveStatus(2); // 强制“正常离园”（按需求可调整为自动判断早退）
//                    record.setCheckOutTime(checkTime);
//                    record.setCheckOutMediaUrl(image);
//
//                    resultRecord = checkRecordRepository.save(record);
//                    log.info("幼儿[childrenId:{}]强制出园成功，状态：2（正常），打卡时间：{}",
//                            childrenId, checkTime);
//                } else {
//                    resultRecord = record;
//                    log.info("幼儿[childrenId:{}]已存在离园记录（状态：{}），无需重复出园",
//                            childrenId, record.getLeaveStatus());
//                }
//            } else {
//                log.warn("幼儿[childrenId:{}]无入园记录（状态：0），拒绝强制出园", childrenId);
//            }
//        }
//
//        // 13. 同步更新考勤流水记录（ChildrenNurseryInfoRecord）：保持原逻辑，补充状态字段
//        if (resultRecord != null) {
//            int day = DateUtil.birthdayDay(end, begin) + 1;
//            List<ChildrenNurseryInfoRecord> nurseryRecordList = childrenNurseryInfoRecordRepository.findAllByAndChildrenIdTime(children.getId(), end, begin);
//
//            // 当天无流水记录则新建（避免重复）
//            if (nurseryRecordList.isEmpty()) {
//                // 同步更新幼儿扩展信息（最新打卡状态）
//                ChildrenExtendInfo childrenExtendInfo = childrenExtendInfoRepository.findByChildrenId(childrenId);
//                if (childrenExtendInfo != null) {
//                    // 扩展信息的状态可设为“最终状态”：有离园则用离园状态，无则用入园状态
//                    int finalStatus = resultRecord.getLeaveStatus() != 0 ? resultRecord.getLeaveStatus() : resultRecord.getStatus();
//                    childrenExtendInfo.setCheckStatus(finalStatus);
//                    childrenExtendInfo.setCheckTime(checkTime);
//                    childrenExtendInfoRepository.save(childrenExtendInfo);
//                    log.info("幼儿[childrenId:{}]扩展信息更新成功，最新状态：{}", childrenId, finalStatus);
//                }
//
//                // 新建考勤流水记录
//                ChildrenNurseryInfoRecord nurseryRecord = new ChildrenNurseryInfoRecord();
//                nurseryRecord.setAreaId(checker.getAreaId());
//                nurseryRecord.setChildrenId(children.getId());
//                nurseryRecord.setChildrenName(children.getName());
//                nurseryRecord.setStatus(resultRecord.getStatus()); // 流水记录同步入园状态
//                nurseryRecord.setLeaveStatus(resultRecord.getLeaveStatus()); // 流水记录同步离园状态（新增）
//                nurseryRecord.setHealthyStatus(0);
//                nurseryRecord.setBeginDate(begin);
//                nurseryRecord.setEndDate(end);
//                nurseryRecord.setEffectDay(day);
//                nurseryRecord.setType(0);
//                nurseryRecord.setPersonTemperature(personTemperature);
//
//                // 同步幼儿 nursery 相关信息（如有）
//                if (childrenExtendInfo != null) {
//                    nurseryRecord.setNurseryOriginalEndDate(childrenExtendInfo.getNurseryEndDate());
//                    nurseryRecord.setNurseryEndDate(childrenExtendInfo.getNurseryEndDate());
//                    nurseryRecord.setSurplusOriginalLeaveDay(childrenExtendInfo.getSurplusLeaveDay());
//                    nurseryRecord.setSurplusLeaveDay(childrenExtendInfo.getSurplusLeaveDay());
//                }
//
//                childrenNurseryInfoRecordRepository.save(nurseryRecord);
//                log.info("幼儿[childrenId:{}]考勤流水记录新建成功", childrenId);
//            }
//        }
//
//        return resultRecord;
//    }
//
//// ------------------------------ 辅助方法（保持不变，仅补充日志） ------------------------------
//    /**
//     * 入园时间范围判断：5:00 ~ 应入园时间+90分钟
//     */
//    private boolean isInCheckInTimeRange(LocalDateTime checkLocalTime, CheckInRule rule) {
//        LocalDateTime ruleCheckInTime = rule.getCheckInTime();
//        LocalDateTime shouldCheckInTime = LocalDateTime.of(
//                checkLocalTime.getYear(), checkLocalTime.getMonth(), checkLocalTime.getDayOfMonth(),
//                ruleCheckInTime.getHour(), ruleCheckInTime.getMinute(), 0
//        );
//
//        LocalDateTime checkInStart = LocalDateTime.of(
//                checkLocalTime.getYear(), checkLocalTime.getMonth(), checkLocalTime.getDayOfMonth(),
//                5, 0, 0
//        );
//        LocalDateTime checkInEnd = shouldCheckInTime.plusMinutes(90);
//
//        boolean isInRange = !checkLocalTime.isBefore(checkInStart) && !checkLocalTime.isAfter(checkInEnd);
//        log.info("幼儿入园时间校验：应入园时间={}，有效范围={}~{}，当前打卡时间={}，是否在范围内={}",
//                shouldCheckInTime, checkInStart, checkInEnd, checkLocalTime, isInRange);
//        return isInRange;
//    }
//
//    /**
//     * 出园时间范围判断：应出园时间-90分钟 ~ 当天23:59:00
//     */
//    private boolean isInCheckOutTimeRange(LocalDateTime checkLocalTime, CheckInRule rule) {
//        LocalDateTime ruleCheckOutTime = rule.getCheckOutTime();
//        LocalDateTime shouldCheckOutTime = LocalDateTime.of(
//                checkLocalTime.getYear(), checkLocalTime.getMonth(), checkLocalTime.getDayOfMonth(),
//                ruleCheckOutTime.getHour(), ruleCheckOutTime.getMinute(), 0
//        );
//
//        LocalDateTime checkOutStart = shouldCheckOutTime.minusMinutes(90);
//        LocalDateTime checkOutEnd = LocalDateTime.of(
//                checkLocalTime.getYear(), checkLocalTime.getMonth(), checkLocalTime.getDayOfMonth(),
//                23, 59, 0
//        );
//
//        boolean isInRange = !checkLocalTime.isBefore(checkOutStart) && !checkLocalTime.isAfter(checkOutEnd);
//        log.info("幼儿出园时间校验：应出园时间={}，有效范围={}~{}，当前打卡时间={}，是否在范围内={}",
//                shouldCheckOutTime, checkOutStart, checkOutEnd, checkLocalTime, isInRange);
//        return isInRange;
//    }
    public CheckRecord checkinChildren(Checker checker, String childrenId, String captureImage, Date checkTime, double personTemperature){
        // 1. 定义当天时间范围（0点-23:59:59）
        Date now = new Date();
        String currentDay = DateUtil.millisToDateTime(now.getTime(), "yyyy-MM-dd");
        Map<String, Date> map = DateUtil.getCurrentDayBeginAndEnd(currentDay);
        Date begin = map.get("beg");
        Date end = map.get("end");

        // 2. 查询幼儿信息（基础校验）
        Children children = childrenRepository.findFirstById(childrenId);
        if (children == null) {
            return null;
        }

        // 3. 获取启用的考勤规则（无规则则不处理）
        CheckInRule rule = checkInRulerRepository.findByEnableStatusAndAreaIdAndDel_flag(1, children.getAreaId(),"0");
        if (rule == null) {
            return null;
        }

        // 4. 查询当天已有记录（按状态区分入园/出园类型）
        List<CheckRecord> checkInRecords = checkRecordRepository.findByCheckInTimeBetweenAndChildrenIdAndStatusIn(
                begin, end, childrenId, Arrays.asList(1, 5)
        );
        // 优化打印：遍历入园记录
        if (checkInRecords.isEmpty()) {
            log.info("当前幼儿[childrenId:{}]当天无入园记录（status=1/5）", childrenId);
        } else {
            log.info("当前幼儿[childrenId:{}]当天入园记录共{}条：", childrenId, checkInRecords.size());
            for (int i = 0; i < checkInRecords.size(); i++) {
                log.info("入园记录[{}]：{}", i + 1, checkInRecords.get(i));
            }
        }

        List<CheckRecord> checkOutRecords = checkRecordRepository.findByCheckInTimeBetweenAndChildrenIdAndStatusIn(
                begin, end, childrenId, Arrays.asList(2, 6)
        );
        // 优化打印：遍历出园记录
        if (checkOutRecords.isEmpty()) {
            log.info("当前幼儿[childrenId:{}]当天无出园记录（status=2/6）", childrenId);
        } else {
            log.info("当前幼儿[childrenId:{}]当天出园记录共{}条：", childrenId, checkOutRecords.size());
            for (int i = 0; i < checkOutRecords.size(); i++) {
                log.info("出园记录[{}]：{}", i + 1, checkOutRecords.get(i));
            }
        }

        // 5. 关联班级信息
        RelClassesChildren relClassesChildren = relClassesChildrenRepository.findFirstByChildrenId(childrenId);
        String classesId = relClassesChildren != null ? relClassesChildren.getClassesId() : null;

        // 6. 转换打卡时间为LocalDateTime（便于时间比较）
        LocalDateTime checkLocalTime = checkTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();

        // 7. 验证当天是否是打卡日
        boolean isCheckDay = false;
        if (StringUtils.hasText(rule.getCheckDays())) {
            int currentWeekDay = checkLocalTime.getDayOfWeek().getValue(); // 1=周一，7=周日
            String[] checkDayArr = rule.getCheckDays().split(",");
            log.info("考勤规则checkDays：{}，拆分后：{}，当前星期：{}",
                    rule.getCheckDays(), Arrays.toString(checkDayArr), currentWeekDay);

            isCheckDay = Arrays.asList(rule.getCheckDays().split(",")).contains(String.valueOf(currentWeekDay));
        }
        if (!isCheckDay) {
            return null; // 非打卡日不处理
        }
        String image = "";
        if (org.apache.commons.lang3.StringUtils.isNotBlank(captureImage)) {
            String fileName = "photo.jpg";
//            MultipartFile fileV1 = Base64ToFile.base64ToMultipartFile1(captureImage, fileName);

//            image = uploadService.uploadCheckInRecordImg(childrenId, fileV1);
            // 8. 核心修复：Base64 图片处理（预处理+解码+上传，含异常捕获）
             image = handleCaptureImage(childrenId, captureImage);

        }
        CheckRecord resultRecord = null;

        // 8. 处理考勤机方向逻辑
        if (checker.getDirection() == 3) { // 自动判断入园/出园
            // 8.1 入园逻辑（仅在无入园记录且在入园时间范围内）
            if (checkInRecords.isEmpty() && isInCheckInTimeRange(checkLocalTime, rule)) {
                CheckRecord checkInRecord = new CheckRecord();
                checkInRecord.setChildrenId(childrenId);
                checkInRecord.setClassesId(classesId);
                checkInRecord.setUserType(1); // 幼儿
                checkInRecord.setCheckerId(checker.getId());
                checkInRecord.setCheckerAddress(checker.getAddress());
                if (personTemperature != 0.0) {
                    // 保留小数点后一位（自动四舍五入）
                    String formattedTemp = String.format("%.1f", personTemperature);
                    checkInRecord.setTemperature(formattedTemp);
                } else {
                    // 若值不存在，可根据需求设置为null或空字符串
                    checkInRecord.setTemperature(""); // 或 ""
                }
//                checkInRecord.setTemperature(String.valueOf(personTemperature));
                checkInRecord.setCheckInTime(checkTime);
                checkInRecord.setCheckInMediaUrl(image);
                checkInRecord.setGroupFlag(currentDay); // 日期分组标识

                // 1. 生成当前打卡日的应入园时间（和isInCheckInTimeRange方法逻辑一致，确保日期正确）
                LocalDateTime ruleCheckInTime = rule.getCheckInTime();
                LocalDateTime shouldCheckInTime = LocalDateTime.of(
                        checkLocalTime.getYear(),    // 当前打卡日的年
                        checkLocalTime.getMonth(),   // 当前打卡日的月
                        checkLocalTime.getDayOfMonth(), // 当前打卡日的日
                        ruleCheckInTime.getHour(),   // 规则的时（如14）
                        ruleCheckInTime.getMinute(), // 规则的分（如50）
                        0 // 秒（默认0）
                );

                // 2. 处理lateAbsentRule为null或负数的情况（默认阈值10分钟）
                int lateThreshold = Optional.ofNullable(rule.getLateAbsentRule())
                        .filter(threshold -> threshold >= 0) // 过滤负数阈值
                        .orElse(10); // 阈值为null/负数时，默认10分钟

                // 3. 计算迟到分钟数（当前打卡时间 - 应入园时间，正数=迟到，负数=提前）
                long lateMinutes = ChronoUnit.MINUTES.between(shouldCheckInTime, checkLocalTime);

                // 4. 打印关键日志，便于验证
                log.info("迟到判断详情：应入园时间={}（当前日），实际打卡时间={}，迟到分钟数={}，阈值={}",
                        shouldCheckInTime, checkLocalTime, lateMinutes, lateThreshold);

                // 5. 正确设置状态：迟到分钟数>阈值→迟到（5），否则正常（1）
                checkInRecord.setStatus(lateMinutes > lateThreshold ? 5 : 1);
                // ----------------------------------------------------------------------

                resultRecord = checkRecordRepository.save(checkInRecord);
                Integer tuoRemainingNum = children.getTuoRemainingNum();
                Integer lastTuoNum = children.getLastTuoNum();
                //25-10-13 打卡就扣除一天托育天数
                if (tuoRemainingNum !=null&&!tuoRemainingNum.equals(0)){
                    if (lastTuoNum !=null){
                        if (lastTuoNum >0){
                            children.setLastTuoNum(lastTuoNum - 1);
                        }else  if (lastTuoNum == 0) {
                            children.setTuoRemainingNum(tuoRemainingNum - 1);
                        }
                    }else {
                        children.setTuoRemainingNum(tuoRemainingNum - 1);
                    }
                    childrenRepository.save(children);
                }

                log.info("生成入园记录：childrenId={}，status={}（1=正常，5=迟到）",
                        childrenId, checkInRecord.getStatus());
            }
            // 8.2 出园逻辑（仅在有入园记录且在出园时间范围内）
            else if (!checkInRecords.isEmpty() && isInCheckOutTimeRange(checkLocalTime, rule)) {
                CheckRecord checkOutRecord;
                // 关键：判断是否已有出园记录（包括早退status=6、正常出园status=2）
                if (!checkOutRecords.isEmpty()) {
                    // 复用已有出园记录（取最新一条，按打卡时间排序）
                    checkOutRecord = checkOutRecords.stream()
                            .max(Comparator.comparing(CheckRecord::getCheckOutTime)) // 按出园时间取最新
                            .orElse(new CheckRecord());
                    log.info("复用已有出园记录：childrenId={}，原状态={}，将更新为新状态",
                            childrenId, checkOutRecord.getStatus());
                } else {
                    // 无出园记录，新建
                    checkOutRecord = new CheckRecord();
                    checkOutRecord.setChildrenId(childrenId);
                    checkOutRecord.setClassesId(classesId);
                    checkOutRecord.setUserType(1); // 幼儿
                    checkOutRecord.setCheckerId(checker.getId());
                    checkOutRecord.setCheckerAddress(checker.getAddress());
                    checkOutRecord.setGroupFlag(currentDay);
                }

                // 更新出园信息（覆盖原有字段）
                checkOutRecord.setCheckOutTime(checkTime);
                checkOutRecord.setCheckInTime(checkTime);
                checkOutRecord.setCheckOutMediaUrl(image);
//                checkOutRecord.setTemperature(String.valueOf(personTemperature));
//                checkOutRecord.setTemperature1(String.valueOf(personTemperature));

                if (personTemperature != 0.0) {
                    // 保留小数点后一位（自动四舍五入）
                    String formattedTemp = String.format("%.1f", personTemperature);
                    checkOutRecord.setTemperature1(formattedTemp);
                } else {
                    // 若值不存在，可根据需求设置为null或空字符串
                    checkOutRecord.setTemperature1(""); // 或 ""
                }
                // 1. 生成当前打卡日的应出园时间
                LocalDateTime ruleCheckOutTime = rule.getCheckOutTime();
                LocalDateTime shouldCheckOutTime = LocalDateTime.of(
                        checkLocalTime.getYear(),
                        checkLocalTime.getMonth(),
                        checkLocalTime.getDayOfMonth(),
                        ruleCheckOutTime.getHour(),
                        ruleCheckOutTime.getMinute(),
                        0
                );

                // 2. 处理早退阈值（默认30分钟）
                int earlyThreshold = Optional.ofNullable(rule.getEarlyAbsentRule())
                        .filter(threshold -> threshold >= 0)
                        .orElse(30);

                // 3. 计算提前分钟数
                long earlyMinutes = ChronoUnit.MINUTES.between(checkLocalTime, shouldCheckOutTime);
                log.info("早退判断详情：应出园时间={}，实际打卡时间={}，提前分钟数={}，阈值={}",
                        shouldCheckOutTime, checkLocalTime, earlyMinutes, earlyThreshold);

                // 4. 更新状态（覆盖原有状态：早退→正常，或保持正常）
                checkOutRecord.setStatus(earlyMinutes > earlyThreshold ? 6 : 2);

                // 保存更新后的记录（若复用已有记录，会执行UPDATE；若新建，执行INSERT）
                resultRecord = checkRecordRepository.save(checkOutRecord);
                log.info("更新出园记录：childrenId={}，新状态={}（2=正常，6=早退）",
                        childrenId, checkOutRecord.getStatus());
            }
        }
        // 9. 处理方向1（仅入园）
        else if (checker.getDirection() == 1) {
            if (checkInRecords.isEmpty()) { // 仅在无入园记录时新增
                CheckRecord checkInRecord = new CheckRecord();
                checkInRecord.setChildrenId(childrenId);
                checkInRecord.setClassesId(classesId);
                checkInRecord.setUserType(1);
                checkInRecord.setCheckerId(checker.getId());
                checkInRecord.setCheckerAddress(checker.getAddress());
                checkInRecord.setCheckInTime(checkTime);
                checkInRecord.setCheckInMediaUrl(image);
                checkInRecord.setStatus(1); // 强制正常入园
                checkInRecord.setGroupFlag(currentDay);

                resultRecord = checkRecordRepository.save(checkInRecord);
            } else {
                resultRecord = checkInRecords.get(0); // 已有入园记录，返回第一条
            }
        }
        // 10. 处理方向2（仅出园）
        else if (checker.getDirection() == 2) {
            if (!checkInRecords.isEmpty()) { // 必须有入园记录才允许出园
                CheckRecord checkOutRecord;
                if (!checkOutRecords.isEmpty()) {
                    checkOutRecord = checkOutRecords.get(0); // 复用已有出园记录
                } else {
                    checkOutRecord = new CheckRecord();
                    checkOutRecord.setChildrenId(childrenId);
                    checkOutRecord.setClassesId(classesId);
                    checkOutRecord.setUserType(1);
                    checkOutRecord.setCheckerId(checker.getId());
                    checkOutRecord.setCheckerAddress(checker.getAddress());
                    checkOutRecord.setGroupFlag(currentDay);
                }

                checkOutRecord.setCheckOutTime(checkTime);
                checkOutRecord.setCheckOutMediaUrl(image);
                checkOutRecord.setStatus(2); // 强制正常出园

                resultRecord = checkRecordRepository.save(checkOutRecord);
            }
        }

        // 11. 处理考勤流水记录
        if (resultRecord != null) {
            int day = DateUtil.birthdayDay(end, begin) + 1;
            List<ChildrenNurseryInfoRecord> list = childrenNurseryInfoRecordRepository.findAllByAndChildrenIdTime(children.getId(), end, begin);

            if (list.isEmpty()) {
                ChildrenExtendInfo childrenExtendInfo = childrenExtendInfoRepository.findByChildrenId(childrenId);
                if (childrenExtendInfo != null) {
                    childrenExtendInfo.setCheckStatus(resultRecord.getStatus());
                    childrenExtendInfo.setCheckTime(checkTime);
                    childrenExtendInfoRepository.save(childrenExtendInfo);
                }

                // 添加考勤流水记录
                ChildrenNurseryInfoRecord nurseryRecord = new ChildrenNurseryInfoRecord();
                nurseryRecord.setAreaId(checker.getAreaId());
                nurseryRecord.setChildrenId(children.getId());
                nurseryRecord.setChildrenName(children.getName());
                nurseryRecord.setStatus(resultRecord.getStatus());
                nurseryRecord.setHealthyStatus(0);
                nurseryRecord.setBeginDate(begin);
                nurseryRecord.setEndDate(end);
                nurseryRecord.setEffectDay(day);
                nurseryRecord.setType(0);
                nurseryRecord.setPersonTemperature(personTemperature);

                if (childrenExtendInfo != null) {
                    nurseryRecord.setNurseryOriginalEndDate(childrenExtendInfo.getNurseryEndDate());
                    nurseryRecord.setNurseryEndDate(childrenExtendInfo.getNurseryEndDate());
                    nurseryRecord.setSurplusOriginalLeaveDay(childrenExtendInfo.getSurplusLeaveDay());
                    nurseryRecord.setSurplusLeaveDay(childrenExtendInfo.getSurplusLeaveDay());
                }

                childrenNurseryInfoRecordRepository.save(nurseryRecord);
            }
        }

        return resultRecord;
    }

    // 入园时间范围判断（辅助方法）
    public boolean isInCheckInTimeRange(LocalDateTime checkLocalTime, CheckInRule rule) {
        // 1. 从规则中获取应入园的时分秒（忽略规则中的日期，仅保留时分秒）
        LocalDateTime ruleCheckInTime = rule.getCheckInTime();
        // 2. 构建当前打卡日的应入园时间（用打卡日的年/月/日 + 规则的时/分/秒）
        LocalDateTime shouldCheckInTime = LocalDateTime.of(
                checkLocalTime.getYear(),    // 打卡日的年
                checkLocalTime.getMonth(),   // 打卡日的月
                checkLocalTime.getDayOfMonth(), // 打卡日的日
                ruleCheckInTime.getHour(),   // 规则的时（如8）
                ruleCheckInTime.getMinute(), // 规则的分（如0）
                0 // 秒（默认0）
        );

        // 3. 计算入园有效范围（5:00 ~ 应入园时间+60分钟）
        LocalDateTime checkInStart = LocalDateTime.of(
                checkLocalTime.getYear(), checkLocalTime.getMonth(), checkLocalTime.getDayOfMonth(),
                5, 0, 0
        );
        LocalDateTime checkInEnd = shouldCheckInTime.plusMinutes(90); // 正确：当前日的应入园时间+60分钟

        // 打印日志（验证时间范围）
        log.info("入园有效范围：{} ~ {}，当前打卡时间：{}，应入园时间：{}",
                checkInStart, checkInEnd, checkLocalTime, shouldCheckInTime);

        // 4. 判断打卡时间是否在范围内（包含边界）
        return !checkLocalTime.isBefore(checkInStart) && !checkLocalTime.isAfter(checkInEnd);
    }

    // 出园时间范围判断（辅助方法）
    /**
     * 出园时间范围判断（修复：确保应出园时间的日期为当前打卡日）
     * @param checkLocalTime 实际打卡时间（含当前日期）
     * @param rule 考勤规则（仅应出园时间的时分秒有效）
     * @return true=在有效范围内，false=不在
     */
    public boolean isInCheckOutTimeRange(LocalDateTime checkLocalTime, CheckInRule rule) {
        // 1. 从规则中提取应出园的「时分秒」（忽略规则中的日期，仅保留时分秒）
        LocalDateTime ruleCheckOutTime = rule.getCheckOutTime();
        // 2. 构建「当前打卡日」的应出园时间（打卡日的年/月/日 + 规则的时/分/秒）
        LocalDateTime shouldCheckOutTime = LocalDateTime.of(
                checkLocalTime.getYear(),    // 当前打卡日的年份
                checkLocalTime.getMonth(),   // 当前打卡日的月份
                checkLocalTime.getDayOfMonth(), // 当前打卡日的日期
                ruleCheckOutTime.getHour(),   // 规则配置的应出园小时（如17）
                ruleCheckOutTime.getMinute(), // 规则配置的应出园分钟（如0）
                0 // 秒数默认0（规则中秒数无意义）
        );

        // 3. 计算出园有效范围：应出园时间前90分钟 ~ 当天23:59:00
        LocalDateTime checkOutStart = shouldCheckOutTime.minusMinutes(90); // 提前90分钟开始允许出园
        LocalDateTime checkOutEnd = LocalDateTime.of(
                checkLocalTime.getYear(), checkLocalTime.getMonth(), checkLocalTime.getDayOfMonth(),
                23, 59, 0 // 固定当天最晚出园时间
        );

        // 4. 打印日志（验证时间范围是否正确，便于排查问题）
        log.info("出园时间计算：应出园时间={}，有效范围={} ~ {}，当前打卡时间={}",
                shouldCheckOutTime, checkOutStart, checkOutEnd, checkLocalTime);

        // 5. 判断实际打卡时间是否在有效范围内（包含边界值）
        return !checkLocalTime.isBefore(checkOutStart) && !checkLocalTime.isAfter(checkOutEnd);
    }

    @Override
    public CheckRecord checkinChildren1(String childrenId, Date checkTime,Integer status,Integer healthyStatus) {
        Date now = new Date();
        String currentDay = DateUtil.millisToDateTime(now.getTime(), "yyyy-MM-dd");
        Map<String, Date> map = DateUtil.getCurrentDayBeginAndEnd(currentDay);
        Date begin = map.get("beg");
        Date end = map.get("end");
        // 5. 关联班级信息
        RelClassesChildren relClassesChildren = relClassesChildrenRepository.findFirstByChildrenId(childrenId);
        String classesId = relClassesChildren != null ? relClassesChildren.getClassesId() : null;
        // 4. 查询当天已有记录（按状态区分入园/出园类型）
        List<CheckRecord> checkInRecords = checkRecordRepository.findByCheckInTimeBetweenAndChildrenIdAndStatusIn(
                begin, end, childrenId, Arrays.asList(1, 5)
        );
        // 3. 核心逻辑：空则新增，非空则更新
        if (CollectionUtils.isEmpty(checkInRecords)) {
            // 3.1 无记录：新增入园记录（原有逻辑不变）
            CheckRecord checkInRecord = new CheckRecord();
            checkInRecord.setChildrenId(childrenId);
            checkInRecord.setClassesId(classesId);
            checkInRecord.setUserType(1); // 幼儿
//            checkInRecord.setCheckerId(checker.getId());
            checkInRecord.setCheckInTime(checkTime); // 传入的打卡时间
            checkInRecord.setGroupFlag(currentDay); // 日期分组标识
            checkInRecord.setStatus(4); // 传入的状态
            checkInRecord.setHealthyStatus(healthyStatus); // 传入的状态

            // 若后续需要恢复温度、图片字段，直接取消注释赋值即可

            return checkRecordRepository.save(checkInRecord);
        } else {
            // 3.2 有记录：更新已有记录（取第一条，当天同一状态应仅1条）
            CheckRecord existingRecord = checkInRecords.get(0); // 获取当天已有记录

            // 【关键】更新需要变动的字段（不变的字段无需赋值）
            existingRecord.setCheckInTime(checkTime); // 更新为最新的打卡时间
//            existingRecord.setCheckerId(checker.getId()); // 更新打卡人（若可能更换打卡人）
            existingRecord.setStatus(4); // 更新状态（若状态可能变更，如从5改为1）
            existingRecord.setHealthyStatus(healthyStatus); // 传入的状态
            // 若后续需要恢复温度、图片字段，补充更新：
            // existingRecord.setTemperature(String.valueOf(personTemperature));
            // existingRecord.setCheckInMediaUrl(image);

            // JPA save()：有id则更新，无id则新增（此处existingRecord已有id，自动执行更新）
            return checkRecordRepository.save(existingRecord);
        }
    }

    /**
     * 辅助方法3：处理 Base64 图片（预处理+解码+上传，核心修复点）
     */
    private String handleCaptureImage(String childrenId, String captureImage) {
        String imageUrl = "";
        if (StringUtils.isEmpty(captureImage)) {
            log.info("幼儿[childrenId:{}]无打卡图片，跳过图片处理", childrenId);
            return imageUrl;
        }

        try {
            // 步骤1：Base64 预处理（去除前缀、非法字符、补充填充）
            String cleanBase64 = cleanBase64String(captureImage);
            if (cleanBase64 == null) {
                log.warn("幼儿[childrenId:{}]打卡图片 Base64 预处理后为空", childrenId);
                return imageUrl;
            }

            // 步骤2：生成唯一文件名（幼儿ID+时间戳，避免重复）
            String timestamp = String.valueOf(System.currentTimeMillis());
            String fileName = String.format("checkin_%s_%s.jpg", childrenId, timestamp);
            log.info("幼儿[childrenId:{}]生成图片文件名：{}", childrenId, fileName);

            // 步骤3：Base64 转 MultipartFile（用修复后的工具类）
            MultipartFile multipartFile = Base64ToFile.base64ToMultipartFile(cleanBase64, fileName);

            // 步骤4：上传图片到 OSS（原有逻辑）
            imageUrl = uploadService.uploadCheckInRecordImg(childrenId, multipartFile);
            log.info("幼儿[childrenId:{}]打卡图片上传成功，OSS地址：{}", childrenId, imageUrl);

        } catch (Exception e) {
            // 捕获所有异常，避免图片处理失败影响打卡核心流程
            log.error("幼儿[childrenId:{}]打卡图片处理失败", childrenId, e);
            // 可选：抛出业务异常中断打卡，或返回空地址继续打卡（此处选择继续）
            // throw new ServiceException("打卡图片处理失败：" + e.getMessage());
            imageUrl = "";
        }
        return imageUrl;
    }

    /**
     * 辅助方法4：Base64 字符串预处理（解决格式错误）
     */
    private String cleanBase64String(String base64Str) {
        if (StringUtils.isEmpty(base64Str)) {
            return null;
        }

        // 1. 去除 Base64 前缀（如 "data:image/jpeg;base64,"）
        String cleanStr = base64Str;
        if (cleanStr.contains(";base64,")) {
            cleanStr = cleanStr.split(";base64,")[1];
            log.debug("Base64 去除前缀后长度：{}", cleanStr.length());
        }

        // 2. 清理非法字符（空格、换行符、制表符等）
        cleanStr = cleanStr.replaceAll("\\s+", ""); // 匹配所有空白字符
        log.debug("Base64 清理非法字符后长度：{}", cleanStr.length());

        // 3. 补充 Base64 填充符（确保长度是 4 的倍数）
        int mod = cleanStr.length() % 4;
        if (mod != 0) {
            int paddingCount = 4 - mod;
            StringBuilder padding = new StringBuilder();
            for (int i = 0; i < paddingCount; i++) {
                padding.append("=");
            }
            cleanStr += padding.toString();
            log.debug("Base64 补充{}个填充符后长度：{}", paddingCount, cleanStr.length());
        }

        // 4. 验证是否为标准 Base64 字符（提前排查无效字符）
        if (!isValidBase64(cleanStr)) {
            log.error("幼儿打卡图片 Base64 包含非法字符，前20字符：{}...",
                    cleanStr.substring(0, Math.min(20, cleanStr.length())));
            return null;
        }

        return cleanStr;
    }

    /**
     * 辅助方法5：验证 Base64 字符合法性
     */
    private boolean isValidBase64(String str) {
        // 标准 Base64 字符集：A-Z、a-z、0-9、+、/、=（填充符）
        String base64Pattern = "^[A-Za-z0-9+/]+={0,2}$";
        return str.matches(base64Pattern);
    }



    //public CheckRecord checkinChildren(Checker checker, String childrenId, String captureImage, Date checkTime, double personTemperature) {
    //        // 1. 定义当天时间范围（0点-23:59:59）
    //        Date now = new Date();
    //        String currentDay = DateUtil.millisToDateTime(now.getTime(), "yyyy-MM-dd");
    //        Map<String, Date> map = DateUtil.getCurrentDayBeginAndEnd(currentDay);
    //        Date begin = map.get("beg");
    //        Date end = map.get("end");
    //
    //        // 2. 基础校验：幼儿存在性
    //        Children children = childrenRepository.findFirstById(childrenId);
    //        if (children == null) {
    //            log.warn("幼儿[childrenId:{}]不存在，拒绝打卡", childrenId);
    //            return null;
    //        }
    //
    //        // 3. 基础校验：考勤规则存在性（启用状态+对应区域）
    //        CheckInRule rule = checkInRulerRepository.findByEnableStatusAndAreaId(1, children.getAreaId());
    //        if (rule == null) {
    //            log.warn("幼儿[childrenId:{}]所属区域无启用的考勤规则，拒绝打卡", childrenId);
    //            return null;
    //        }
    //
    //        // 4. 核心：查询当天唯一记录（一天一条，复用/新建）
    //        CheckRecord record = checkRecordRepository.findFirstByCheckInTimeBetweenAndChildrenId(begin, end, childrenId);
    //        log.info("幼儿[childrenId:{}]当天记录查询结果：{}",
    //                childrenId, record == null ? "无记录，将创建新记录" : "已存在记录，将更新对应字段");
    //
    //        // 5. 关联班级信息（用于记录班级ID）
    //        RelClassesChildren relClassesChildren = relClassesChildrenRepository.findFirstByChildrenId(childrenId);
    //        String classesId = relClassesChildren != null ? relClassesChildren.getClassesId() : null;
    //
    //        // 6. 时间格式转换（LocalDateTime便于时间范围判断）
    //        LocalDateTime checkLocalTime = checkTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    //
    //        // 7. 校验：当天是否为打卡日（按规则配置的星期几）
    //        boolean isCheckDay = false;
    //        if (StringUtils.hasText(rule.getCheckDays())) {
    //            int currentWeekDay = checkLocalTime.getDayOfWeek().getValue(); // 1=周一，7=周日
    //            isCheckDay = Arrays.asList(rule.getCheckDays().split(",")).contains(String.valueOf(currentWeekDay));
    //        }
    //        if (!isCheckDay) {
    //            log.warn("幼儿[childrenId:{}]当天非打卡日（星期{}），拒绝打卡", childrenId, checkLocalTime.getDayOfWeek().getValue());
    //            return null;
    //        }
    //
    //        // 8. 图片上传（如有）：入园/出园共用同一张图（或按需区分，此处保持原逻辑）
    //        String image = "";
    //        if (org.apache.commons.lang3.StringUtils.isNotBlank(captureImage)) {
    //            String fileName = "checkin_" + childrenId + "_" + System.currentTimeMillis() + ".jpg"; // 文件名加时间戳，避免重复
    //            MultipartFile fileV1 = Base64ToFile.base64ToMultipartFile(captureImage, fileName);
    //            image = uploadService.uploadCheckInRecordImg(childrenId, fileV1);
    //            log.info("幼儿[childrenId:{}]打卡图片上传完成，路径：{}", childrenId, image);
    //        }
    //
    //        // 9. 初始化记录（无记录则新建，有记录则复用）
    //        if (record == null) {
    //            record = new CheckRecord();
    //            // 基础字段初始化（仅新建时设置，后续更新不覆盖）
    //            record.setChildrenId(childrenId);
    //            record.setClassesId(classesId);
    //            record.setUserType(1); // 固定为“幼儿”类型
    //            record.setCheckerId(checker.getId());
    //            record.setCheckerAddress(checker.getAddress());
    //            record.setGroupFlag(currentDay); // 日期分组标识（便于后续查询）
    //            // 状态字段默认值（数据库已设default 0，代码显式设置更安全）
    //            record.setStatus(0); // 入园状态默认“缺席”
    //            record.setLeaveStatus(0); // 离园状态默认“未离园”
    //        }
    //        // 每次打卡都更新最新温度（无论入园/出园）
    //        record.setTemperature(String.valueOf(personTemperature));
    //
    //        CheckRecord resultRecord = null;
    //
    //        // 10. 处理考勤机方向：3=自动判断入园/出园（核心场景）
    //        if (checker.getDirection() == 3) {
    //            // 10.1 自动判断：入园操作（满足2个条件：未记录入园状态 + 在入园时间范围内）
    //            if (record.getStatus() == 0 && isInCheckInTimeRange(checkLocalTime, rule)) {
    //                // 计算入园状态（正常1 / 迟到5）
    //                LocalDateTime ruleCheckInTime = rule.getCheckInTime();
    //                LocalDateTime shouldCheckInTime = LocalDateTime.of(
    //                        checkLocalTime.getYear(), checkLocalTime.getMonth(), checkLocalTime.getDayOfMonth(),
    //                        ruleCheckInTime.getHour(), ruleCheckInTime.getMinute(), 0
    //                );
    //                // 迟到阈值：规则有值则用规则，无则默认10分钟（过滤负数）
    //                int lateThreshold = Optional.ofNullable(rule.getLateAbsentRule())
    //                        .filter(threshold -> threshold >= 0)
    //                        .orElse(10);
    //                long lateMinutes = ChronoUnit.MINUTES.between(shouldCheckInTime, checkLocalTime);
    //
    //                // 更新入园相关字段（仅更新入园状态，不碰离园字段）
    //                record.setStatus(lateMinutes > lateThreshold ? 5 : 1); // 迟到→5，正常→1
    //                record.setCheckInTime(checkTime);
    //                record.setCheckInMediaUrl(image);
    //
    //                resultRecord = checkRecordRepository.save(record);
    //                log.info("幼儿[childrenId:{}]自动入园成功，状态：{}（1=正常，5=迟到），打卡时间：{}",
    //                        childrenId, record.getStatus(), checkTime);
    //
    //                // 10.2 自动判断：出园操作（满足2个条件：已记录入园状态 + 在出园时间范围内）
    //            } else if (record.getStatus() != 0 && isInCheckOutTimeRange(checkLocalTime, rule)) {
    //                // 计算离园状态（正常2 / 早退6）
    //                LocalDateTime ruleCheckOutTime = rule.getCheckOutTime();
    //                LocalDateTime shouldCheckOutTime = LocalDateTime.of(
    //                        checkLocalTime.getYear(), checkLocalTime.getMonth(), checkLocalTime.getDayOfMonth(),
    //                        ruleCheckOutTime.getHour(), ruleCheckOutTime.getMinute(), 0
    //                );
    //                // 早退阈值：规则有值则用规则，无则默认30分钟（过滤负数）
    //                int earlyThreshold = Optional.ofNullable(rule.getEarlyAbsentRule())
    //                        .filter(threshold -> threshold >= 0)
    //                        .orElse(30);
    //                long earlyMinutes = ChronoUnit.MINUTES.between(checkLocalTime, shouldCheckOutTime);
    //
    //                // 更新离园相关字段（仅更新离园状态，不碰入园字段）
    //                record.setLeaveStatus(earlyMinutes > earlyThreshold ? 6 : 2); // 早退→6，正常→2
    //                record.setCheckOutTime(checkTime);
    //                record.setCheckOutMediaUrl(image);
    //
    //                resultRecord = checkRecordRepository.save(record);
    //                log.info("幼儿[childrenId:{}]自动出园成功，状态：{}（2=正常，6=早退），打卡时间：{}",
    //                        childrenId, record.getLeaveStatus(), checkTime);
    //            } else {
    //                log.warn("幼儿[childrenId:{}]自动打卡条件不满足：当前入园状态={}，是否在入园范围={}，是否在出园范围={}",
    //                        childrenId, record.getStatus(),
    //                        isInCheckInTimeRange(checkLocalTime, rule),
    //                        isInCheckOutTimeRange(checkLocalTime, rule));
    //            }
    //
    //            // 11. 处理考勤机方向：1=仅入园（强制入园，不判断自动逻辑）
    //        } else if (checker.getDirection() == 1) {
    //            // 仅当入园状态为默认0（未入园）时才更新
    //            if (record.getStatus() == 0) {
    //                record.setStatus(1); // 强制“正常入园”（按需求可调整为自动判断迟到）
    //                record.setCheckInTime(checkTime);
    //                record.setCheckInMediaUrl(image);
    //
    //                resultRecord = checkRecordRepository.save(record);
    //                log.info("幼儿[childrenId:{}]强制入园成功，状态：1（正常），打卡时间：{}",
    //                        childrenId, checkTime);
    //            } else {
    //                resultRecord = record;
    //                log.info("幼儿[childrenId:{}]已存在入园记录（状态：{}），无需重复入园",
    //                        childrenId, record.getStatus());
    //            }
    //
    //            // 12. 处理考勤机方向：2=仅出园（强制出园，不判断自动逻辑）
    //        } else if (checker.getDirection() == 2) {
    //            // 必须有入园记录（status≠0）才允许出园
    //            if (record.getStatus() != 0) {
    //                // 仅当离园状态为默认0（未离园）时才更新
    //                if (record.getLeaveStatus() == 0) {
    //                    record.setLeaveStatus(2); // 强制“正常离园”（按需求可调整为自动判断早退）
    //                    record.setCheckOutTime(checkTime);
    //                    record.setCheckOutMediaUrl(image);
    //
    //                    resultRecord = checkRecordRepository.save(record);
    //                    log.info("幼儿[childrenId:{}]强制出园成功，状态：2（正常），打卡时间：{}",
    //                            childrenId, checkTime);
    //                } else {
    //                    resultRecord = record;
    //                    log.info("幼儿[childrenId:{}]已存在离园记录（状态：{}），无需重复出园",
    //                            childrenId, record.getLeaveStatus());
    //                }
    //            } else {
    //                log.warn("幼儿[childrenId:{}]无入园记录（状态：0），拒绝强制出园", childrenId);
    //            }
    //        }
    //
    //        // 13. 同步更新考勤流水记录（ChildrenNurseryInfoRecord）：保持原逻辑，补充状态字段
    //        if (resultRecord != null) {
    //            int day = DateUtil.birthdayDay(end, begin) + 1;
    //            List<ChildrenNurseryInfoRecord> nurseryRecordList = childrenNurseryInfoRecordRepository.findAllByAndChildrenIdTime(children.getId(), end, begin);
    //
    //            // 当天无流水记录则新建（避免重复）
    //            if (nurseryRecordList.isEmpty()) {
    //                // 同步更新幼儿扩展信息（最新打卡状态）
    //                ChildrenExtendInfo childrenExtendInfo = childrenExtendInfoRepository.findByChildrenId(childrenId);
    //                if (childrenExtendInfo != null) {
    //                    // 扩展信息的状态可设为“最终状态”：有离园则用离园状态，无则用入园状态
    //                    int finalStatus = resultRecord.getLeaveStatus() != 0 ? resultRecord.getLeaveStatus() : resultRecord.getStatus();
    //                    childrenExtendInfo.setCheckStatus(finalStatus);
    //                    childrenExtendInfo.setCheckTime(checkTime);
    //                    childrenExtendInfoRepository.save(childrenExtendInfo);
    //                    log.info("幼儿[childrenId:{}]扩展信息更新成功，最新状态：{}", childrenId, finalStatus);
    //                }
    //
    //                // 新建考勤流水记录
    //                ChildrenNurseryInfoRecord nurseryRecord = new ChildrenNurseryInfoRecord();
    //                nurseryRecord.setAreaId(checker.getAreaId());
    //                nurseryRecord.setChildrenId(children.getId());
    //                nurseryRecord.setChildrenName(children.getName());
    //                nurseryRecord.setStatus(resultRecord.getStatus()); // 流水记录同步入园状态
    //                nurseryRecord.setLeaveStatus(resultRecord.getLeaveStatus()); // 流水记录同步离园状态（新增）
    //                nurseryRecord.setHealthyStatus(0);
    //                nurseryRecord.setBeginDate(begin);
    //                nurseryRecord.setEndDate(end);
    //                nurseryRecord.setEffectDay(day);
    //                nurseryRecord.setType(0);
    //                nurseryRecord.setPersonTemperature(personTemperature);
    //
    //                // 同步幼儿 nursery 相关信息（如有）
    //                if (childrenExtendInfo != null) {
    //                    nurseryRecord.setNurseryOriginalEndDate(childrenExtendInfo.getNurseryEndDate());
    //                    nurseryRecord.setNurseryEndDate(childrenExtendInfo.getNurseryEndDate());
    //                    nurseryRecord.setSurplusOriginalLeaveDay(childrenExtendInfo.getSurplusLeaveDay());
    //                    nurseryRecord.setSurplusLeaveDay(childrenExtendInfo.getSurplusLeaveDay());
    //                }
    //
    //                childrenNurseryInfoRecordRepository.save(nurseryRecord);
    //                log.info("幼儿[childrenId:{}]考勤流水记录新建成功", childrenId);
    //            }
    //        }
    //
    //        return resultRecord;
    //    }
    //
    //// ------------------------------ 辅助方法（保持不变，仅补充日志） ------------------------------
    //    /**
    //     * 入园时间范围判断：5:00 ~ 应入园时间+90分钟
    //     */
    //    private boolean isInCheckInTimeRange(LocalDateTime checkLocalTime, CheckInRule rule) {
    //        LocalDateTime ruleCheckInTime = rule.getCheckInTime();
    //        LocalDateTime shouldCheckInTime = LocalDateTime.of(
    //                checkLocalTime.getYear(), checkLocalTime.getMonth(), checkLocalTime.getDayOfMonth(),
    //                ruleCheckInTime.getHour(), ruleCheckInTime.getMinute(), 0
    //        );
    //
    //        LocalDateTime checkInStart = LocalDateTime.of(
    //                checkLocalTime.getYear(), checkLocalTime.getMonth(), checkLocalTime.getDayOfMonth(),
    //                5, 0, 0
    //        );
    //        LocalDateTime checkInEnd = shouldCheckInTime.plusMinutes(90);
    //
    //        boolean isInRange = !checkLocalTime.isBefore(checkInStart) && !checkLocalTime.isAfter(checkInEnd);
    //        log.info("幼儿入园时间校验：应入园时间={}，有效范围={}~{}，当前打卡时间={}，是否在范围内={}",
    //                shouldCheckInTime, checkInStart, checkInEnd, checkLocalTime, isInRange);
    //        return isInRange;
    //    }
    //
    //    /**
    //     * 出园时间范围判断：应出园时间-90分钟 ~ 当天23:59:00
    //     */
    //    private boolean isInCheckOutTimeRange(LocalDateTime checkLocalTime, CheckInRule rule) {
    //        LocalDateTime ruleCheckOutTime = rule.getCheckOutTime();
    //        LocalDateTime shouldCheckOutTime = LocalDateTime.of(
    //                checkLocalTime.getYear(), checkLocalTime.getMonth(), checkLocalTime.getDayOfMonth(),
    //                ruleCheckOutTime.getHour(), ruleCheckOutTime.getMinute(), 0
    //        );
    //
    //        LocalDateTime checkOutStart = shouldCheckOutTime.minusMinutes(90);
    //        LocalDateTime checkOutEnd = LocalDateTime.of(
    //                checkLocalTime.getYear(), checkLocalTime.getMonth(), checkLocalTime.getDayOfMonth(),
    //                23, 59, 0
    //        );
    //
    //        boolean isInRange = !checkLocalTime.isBefore(checkOutStart) && !checkLocalTime.isAfter(checkOutEnd);
    //        log.info("幼儿出园时间校验：应出园时间={}，有效范围={}~{}，当前打卡时间={}，是否在范围内={}",
    //                shouldCheckOutTime, checkOutStart, checkOutEnd, checkLocalTime, isInRange);
    //        return isInRange;
    //    }
//    public List<CheckRecord> checkinChildren_(Checker checker, String childrenId, String captureImage, Date checkTime ){
//        //今天0点的时间
//        Date baseTime = new Date(DateUtil.startOfDayOfMilli(System.currentTimeMillis()));
//
//        //根据ChildrenId查询当天的考勤记录
//        List<CheckRecord> checkRecordList = checkRecordRepository.findByChildrenIdAndCheckInTimeThan(childrenId, baseTime);
//
//        List<CheckRecord> recordToUpdate = new ArrayList<>();
//        {
//            //先处理离园记录离园
//            for (int i = 0; i < checkRecordList.size(); i++) {
//                CheckRecord childrenRecord = checkRecordList.get(i);
//
//                if (childrenRecord.getChildrenId().equals(o.getUserIdV2())) {
//                    //如果已经有入园记录了，并且是其他方向，不更新入园时间，直接跳过考勤机提交的记录
//                    //总是取最后一次打卡时间当作签退时间
//                    if (checker.getDirection() == 2) {
//                        childrenRecord.setCheckOutTime(checkTime);
//                        childrenRecord.setUserType(1); //幼儿
//                        recordToUpdate.add(childrenRecord);
//                    }
//                }
//            }
//
//            if (recordToUpdate.size() == 0){
//
//                //没有找到记录，则直创建新纪录
//                CheckRecord checkRecord = new CheckRecord();
//                checkRecord.setChildrenId(childrenId);
//                if (checker.getDirection() == 2) {
//                    checkRecord.setCheckOutTime(checkTime);
//                } else {
//                    checkRecord.setCheckInTime(checkTime);
//                }
//                checkRecord.setUserType(1); //幼儿
//
//                recordToUpdate.add(checkRecord);
//            }
//        }
//
//        if (recordToUpdate.size() > 0){
//
//            //如果需要更新，才上传图片
//
//            //
//
//            checkRecordRepository.saveAll(recordToUpdate);
//        }
//
//        return recordToUpdate;
//    }
}
